import { Injectable } from '@angular/core';
import { Observable, BehaviorSubject, forkJoin, of } from 'rxjs';
import { map, switchMap, tap } from 'rxjs/operators';
import { NotifyService } from '@farris/ui-notify';
import {
    FormBasicService, DesignerEnvType, DomService, FarrisMetadataDto, WebCommandMetadata, WebCommandMetadataConvertor
} from '@farris/designer-services';
import { DesignerMetadataService } from '../../../service/designer-metadata.service';

@Injectable()
export class WebcmdMetadataManager extends BehaviorSubject<WebCommandMetadata[]> {
    private webCommands: WebCommandMetadata[] = [];

    constructor(
        private domService: DomService,
        private metadataService: DesignerMetadataService,
        private notifyService: NotifyService,
        private formBasicService: FormBasicService) {
        super([]);
    }

    loadCmdWithDom(): Observable<any> {
        const webcmdInfos = this.domService.getWebCmds();
        // 如果没有变化，则无需刷新界面
        const cmdMap = new Map<string, WebCommandMetadata>();
        this.webCommands.forEach(cmd => {
            cmdMap.set(cmd.Id, cmd);
        });
        const isExternalCmdLoaded = webcmdInfos.every(item => cmdMap.has(item.id));
        let isInternalCmdLoaded = true;

        const loadingCmds = [];
        // 如果刷新的话，dom里记录的全部需要加载
        loadingCmds.push(...webcmdInfos);

        const result = this.metadataService.getMetadataList('.webcmd');
        return result.pipe(
            tap(list => {
                if (!list) {
                    return;
                }
                list.forEach(item => {
                    let extendProperty: any;
                    try {
                        extendProperty = JSON.parse(item.extendProperty);
                    } catch (e) { }

                    if (extendProperty && extendProperty.FormCode !== this.formBasicService.formMetaBasicInfo.code) {
                        // common or other form
                        return;
                    }

                    if (!webcmdInfos.find(webcmdInfo => item.id === webcmdInfo.id)) {
                        // 只要是属于此表单的都需要加载，除非是已经添加到表单中
                        const webcmd = {
                            id: item.id,
                            path: item.relativePath,
                            name: item.fileName
                        };
                        loadingCmds.push(webcmd);
                        if (!cmdMap.has(item.id)) {
                            isInternalCmdLoaded = false;
                        }

                        // 属于当前表单的加到表单dom中
                        webcmdInfos.push(webcmd);
                    }
                });
            }),
            switchMap(() => {
                if (isExternalCmdLoaded && isInternalCmdLoaded) {
                    // 都加载过，没有变化
                    return of(null);
                }
                const obs = new Array();
                this.webCommands = new Array();
                const sessionId = '';

                loadingCmds.forEach(webcmdInfo => {
                    const id = webcmdInfo.id;
                    const ob = new BehaviorSubject({});
                    obs.push(ob);
                    const refMetadaSev = this.metadataService.getMetadata(id);
                    refMetadaSev.subscribe(metadata => {
                        const cmd = new WebCommandMetadataConvertor().InitFromJobject(JSON.parse(metadata.content));
                        this.webCommands.push(cmd);
                        ob.next({});
                        ob.complete();
                    }, () => {
                        ob.next({});
                        ob.complete();
                    });
                });

                return forkJoin(obs).pipe(
                    tap(() => super.next(this.webCommands)),
                    map(() => { })
                );

            })
        );
    }

    /**
     * 添加命令构件
     */
    addCmdMetadata(metadata: FarrisMetadataDto) {
        const webcmd = new WebCommandMetadataConvertor().InitFromJobject(JSON.parse(metadata.content));
        const webcmdList = this.domService.getWebCmds();

        // modify by wang-xh：选择命令后才把构件信息添加到dom中
        let newWebCmd;
        const existingWebcmdIndex = webcmdList.findIndex(item => item.id === webcmd.Id);
        if (existingWebcmdIndex >= 0) {
            // webcmdList[existingWebcmdIndex] = newWebCmd;
            this.notifyService.warning('相同的控制器已经存在');
        } else {
            newWebCmd = {
                id: webcmd.Id,
                path: metadata.relativePath,
                name: metadata.fileName,
                code: metadata.code,
                nameSpace: metadata.nameSpace
            };
            this.webCommands.push(webcmd);
        }

        super.next(this.webCommands);

        // 返回需要新增的构件
        return newWebCmd;
    }
}
